using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.FSharp.Collections;
using System.Management;



namespace GameXNA_Master
{

    public class Rendering : Microsoft.Xna.Framework.DrawableGameComponent
    {
        RenderingData rendering_data = new RenderingData();

        Model enemyModel;
        Model bossModel;

        Camera camera;

        Floor floor = new Floor();

        Texture2D floorTex;
        BasicEffect floorEffect;

        SpriteBatch spriteBatch;
        SpriteFont font;

        Texture2D aim;
        Texture2D whitepixel;
        int aimH, aimW;

        Model ship;
        Model sphere_bullet;
        Model rocket_bullet;
        Model laser_bullet;

        InformationData info;
        public Rendering(Game game)
            : base(game)
        {

            game.Services.AddService(typeof(Floor), floor);
            game.Services.AddService(typeof(RenderingData), rendering_data);
        }


        public override void Initialize()
        {

            camera = (Camera)Game.Services.GetService(typeof(Camera));
            info = (InformationData)Game.Services.GetService(typeof(InformationData));

            floor.Quad(BulletLogic.projectiles_enemies_State.Player.Value.Position.Value + (new Vector3(0, -4, 0)), Vector3.Up, Vector3.Right, 250f, 250f);

            spriteBatch = new SpriteBatch(Game.GraphicsDevice);

            base.Initialize();
        }

        Model skySphere;
        Effect skyEffect;
        protected override void LoadContent()
        {
            enemyModel = Game.Content.Load<Model>(@"Nemici/Invaders");
            bossModel = Game.Content.Load<Model>(@"Nemici/Boss/Ufo");
            ship = Game.Content.Load<Model>(@"Giocatore/Navetta/Gilgamesh");

            skySphere = Game.Content.Load<Model>(@"Sky/SphereHighPoly");
            skyEffect = Game.Content.Load<Effect>(@"Sky/SkySphere");
            TextureCube skyboxTexture = Game.Content.Load<TextureCube>(@"Sky/output");

            sphere_bullet = Game.Content.Load<Model>(@"Arsenale/sphere");
            rocket_bullet = Game.Content.Load<Model>(@"Arsenale/Space_Mine");
            laser_bullet = Game.Content.Load<Model>(@"Arsenale/laser");

            floorTex = Game.Content.Load<Texture2D>("floor");
            aim = Game.Content.Load<Texture2D>(@"Giocatore/crosshair");
            whitepixel = Game.Content.Load<Texture2D>(@"Giocatore/WhitePixel_Health");
            //exp_text = Game.Content.Load<Texture2D>("explode_1");


            font = Game.Content.Load<SpriteFont>("matrix");
            
            skyEffect.Parameters["ViewMatrix"].SetValue(camera.view);
            skyEffect.Parameters["ProjectionMatrix"].SetValue(camera.proj);
            skyEffect.Parameters["SkyboxTexture"].SetValue(skyboxTexture);
            

            foreach (ModelMesh mesh in skySphere.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    part.Effect = skyEffect;
                }
            }

            
            floorEffect = new BasicEffect(Game.GraphicsDevice);
            floorEffect.EnableDefaultLighting();
            floorEffect.World = Matrix.Identity;
            floorEffect.TextureEnabled = true;
            floorEffect.Texture = floorTex;

                        
            var scope = new ManagementScope();

            var query = new ObjectQuery("SELECT * FROM CIM_VideoControllerResolution WHERE NumberOfColors=4294967296 AND RefreshRate<75 AND VerticalResolution>480");

            using (var searcher = new ManagementObjectSearcher(scope, query))
            {
                var results = searcher.Get();

                foreach (var result in results)
                {
                    rendering_data.screenWidthtResolutions.Add((UInt32)result["HorizontalResolution"]);//Width
                    rendering_data.screenHeightResolutions.Add((UInt32)result["VerticalResolution"]); //Height
                   
                }
            }


            rendering_data.screenHeight = Game.GraphicsDevice.Viewport.Height;
            rendering_data.screenWidth = Game.GraphicsDevice.Viewport.Width;
            rendering_data.aspectRatio = Game.GraphicsDevice.Viewport.AspectRatio;


            rendering_data.aimDim.Y = aimH = aim.Height;
            rendering_data.aimDim.X = aimW = aim.Width;

            BulletLogic.ListPNGModel = new List<Model>() { enemyModel, bossModel };         // dal piu debole al piu forte
            BulletLogic.ListWeapons = new List<Model>() { sphere_bullet, laser_bullet , rocket_bullet };
            BulletLogic.PlayerShipModel = ship;

            base.LoadContent();
        }

        protected override void Dispose(bool disposing)
        {
            Game.Services.RemoveService(typeof(RenderingData));

            base.Dispose(disposing);
        }


        private void DrawEnemyWithEffect(Model model, Object world, Matrix view, Matrix proj)
        {

            foreach (var en in BulletLogic.projectiles_enemies_State.Enemies.Value)
            {
                if (en != null)
                {
                    foreach (ModelMesh mesh in model.Meshes)
                    {
                        foreach (BasicEffect basicEffect in mesh.Effects)
                        {
                            basicEffect.EnableDefaultLighting();
                            basicEffect.DiffuseColor = en.myColor;

                            basicEffect.SpecularColor = new Vector3(0.2f, 0.2f, 0.2f);
                            basicEffect.SpecularPower = 5.0f;
                            basicEffect.AmbientLightColor = new Vector3(0.5f, 0.5f, 0.5f);

                            basicEffect.DirectionalLight0.Enabled = true;
                            basicEffect.DirectionalLight0.DiffuseColor = en.myColor;
                            basicEffect.DirectionalLight0.Direction = Vector3.Normalize(new Vector3(0.0f, 0.0f, 1.0f));
                            basicEffect.DirectionalLight0.SpecularColor = Vector3.One;



                            basicEffect.World = Matrix.CreateTranslation(en.getPosition) * Matrix.CreateScale(1f, 1f, 1f);
                            basicEffect.View = view;
                            basicEffect.Projection = proj;
                        }
                        mesh.Draw();
                    }
                }
            }

        }

        private void DrawBossWithEffect(Model model, Object world, Matrix view, Matrix proj)
        {
                BulletLogic.Enemy b = BulletLogic.projectiles_enemies_State.Boss.Value;
                if (b != null)
                {
                    foreach (ModelMesh mesh in model.Meshes)
                    {
                        foreach (BasicEffect basicEffect in mesh.Effects)
                        {
                            basicEffect.EnableDefaultLighting();
                            basicEffect.DiffuseColor = b.myColor;

                            basicEffect.SpecularColor = new Vector3(0.2f, 0.2f, 0.2f);
                            basicEffect.SpecularPower = 5.0f;
                            basicEffect.AmbientLightColor = new Vector3(0.5f, 0.5f, 0.5f);

                            basicEffect.DirectionalLight0.Enabled = true;
                            basicEffect.DirectionalLight0.DiffuseColor = b.myColor;
                            basicEffect.DirectionalLight0.Direction = Vector3.Normalize(new Vector3(0.0f, 0.0f, 1.0f));
                            basicEffect.DirectionalLight0.SpecularColor = Vector3.One;



                            basicEffect.World = Matrix.CreateTranslation(b.getPosition);
                            basicEffect.View = view;
                            basicEffect.Projection = proj;
                        }
                        mesh.Draw();
                    }
                }
            
        }

        private void DrawBulletModel(Model model, Object world, Matrix view, Matrix proj)
        {

            
            foreach (var bullet in BulletLogic.projectiles_enemies_State.Projectiles.Value)
            {
                    model = BulletLogic.ListWeapons[bullet.Type];

                    foreach (ModelMesh mesh in model.Meshes)
                    {
                        foreach (BasicEffect basicEffect in mesh.Effects)
                        {
                            basicEffect.EnableDefaultLighting();

                            basicEffect.DiffuseColor = bullet.myColor;
                            basicEffect.SpecularColor = new Vector3(0f, 0f, 0f);
                            basicEffect.SpecularPower = 5.0f;
                            basicEffect.AmbientLightColor = new Vector3(1f, 1f, 1f);



                            basicEffect.World = bullet.Rotation.Value* Matrix.CreateTranslation(bullet.Position.Value); 
                            basicEffect.View = view;
                            basicEffect.Projection = proj;
                        }
                        mesh.Draw();
                    }
                
            }
        }

        private void DrawSky()
        {
            skyEffect.Parameters["ViewMatrix"].SetValue(camera.view);
            skyEffect.Parameters["ProjectionMatrix"].SetValue(camera.proj);

            foreach (ModelMesh mesh in skySphere.Meshes)
            {
                mesh.Draw();
            }
            
        }

        private void DrawShipModel(Model model, Matrix view, Matrix proj){
            
            Matrix world = Matrix.CreateTranslation(BulletLogic.projectiles_enemies_State.Player.Value.Position.Value) * Matrix.CreateScale(1f, 1f, 1f);

                foreach (ModelMesh mesh in ship.Meshes)
                {
                
                   foreach (EnvironmentMapEffect basicEffect in mesh.Effects)
                    {
                        basicEffect.EnvironmentMap = Game.Content.Load<TextureCube>("Sky/output");

                        basicEffect.FresnelFactor = 0;

                        basicEffect.World = world;
                        basicEffect.View = camera.view;
                        basicEffect.Projection = camera.proj;
                    }
                    mesh.Draw();
                }
        }


        private const int BAR_LENGTH = 15;


        private void DrawHealthBar(GameTime gameTime, Vector2 position,float z,int life)
        {

            int tmp = life * 10;
            int lunghezza = (int)(BAR_LENGTH * tmp / 100);

           
            spriteBatch.Draw(whitepixel, new Rectangle((int)position.X - 5, (int)position.Y, BAR_LENGTH, 2),null, new Color(new Vector4(255.0f, 0.0f, 0.0f, 0.5f)),0f,Vector2.Zero,SpriteEffects.None,z);
            spriteBatch.Draw(whitepixel, new Rectangle((int)position.X - 5, (int)position.Y, lunghezza, 2), null, new Color(new Vector4(0.0f, 255.0f, 0.0f, 0.5f)), 0f, Vector2.Zero, SpriteEffects.None, z);
            spriteBatch.DrawString(font, tmp + "%", position, new Color(new Vector4(Color.Black.R, Color.Black.G, Color.Black.B, 1)), 0, Vector2.Zero, 0.03f, SpriteEffects.None, z);

        }

        private Vector3 oldposition = Vector3.Zero;
        private Vector3 currentposition = Vector3.Zero;

        public override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            
            

            if (!gameInfoState.pause)
            {               

                /*
                 PAVIMENTO
                */
                floorEffect.View = camera.view;
                floorEffect.Projection = camera.proj;

                foreach (EffectPass pass in floorEffect.CurrentTechnique.Passes)
                {
                    pass.Apply();

                    Game.GraphicsDevice.DrawUserIndexedPrimitives
                        <VertexPositionNormalTexture>(
                        PrimitiveType.TriangleList,
                        floor.Vertices, 0, 4,
                        floor.Indexes, 0, 2);

                }

              

                /*
                 * PROIETTILI
                 */
                
                DrawBulletModel(sphere_bullet, null, camera.view, camera.proj);

                /*
                 * NAVICELLA
                 */

                DrawShipModel(ship, camera.view, camera.proj);

                

                /*
                 * NEMICI
                 */
                if ( !BulletLogic.projectiles_enemies_State.invokeBoss.Value || !(BulletLogic.projectiles_enemies_State.Boss.Value.Life > 0))
                    DrawEnemyWithEffect(enemyModel, null, camera.view, camera.proj);
                else
                    DrawBossWithEffect(bossModel, null, camera.view, camera.proj);


                DrawSky();

                
                /*
                    CROSSHAIR , PUNTEGGI ETC
                 */
                spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.AnisotropicWrap, DepthStencilState.Default, null, null, Matrix.CreateScale(rendering_data.screenWidth / 100.0f, rendering_data.screenHeight / 100.0f, 1.0f));


                DrawHealthBar(gameTime, new Vector2(10, 97f), 0, BulletLogic.projectiles_enemies_State.Player.Value.Life);
                if (BulletLogic.projectiles_enemies_State.invokeBoss.Value)
                {
                    
                    Vector3 position = GraphicsDevice.Viewport.Project(BulletLogic.projectiles_enemies_State.Boss.Value.Position.Value, camera.proj, camera.view,camera.world);

                    DrawHealthBar(gameTime, new Vector2((position.X / rendering_data.screenWidth) * 100, (position.Y / rendering_data.screenHeight) * 100 - 12), 0.1f, BulletLogic.projectiles_enemies_State.Boss.Value.Life);
                    Console.WriteLine(position);


                }
               /* spriteBatch.DrawString(font,
                    "FPS: " + info.fps + "\nTime: " + info.Time(),
                     new Vector2(85, 2),
                     Color.LightGreen, 0, Vector2.Zero, 0.06f, SpriteEffects.None, 0f);*/

                

                spriteBatch.Draw(aim, new Vector2(50 - aimW / 200, 50 - aimH / 200), null, Color.White, 0, new Vector2(aimW / 2, aimH / 2), 0.06f, SpriteEffects.None, 0f);
                spriteBatch.Draw(Game.Content.Load<Texture2D>("Giocatore/VEtro Ship"), new Rectangle(0, 0, 100, 100), Color.White);

                spriteBatch.DrawString(font,
                   "Score: " + (String.Format("{0:0,0}", BulletLogic.projectiles_enemies_State.Score.Value * 100)).Replace('.', '\''),
                    new Vector2(85, 2),
                    Color.LightGreen, 0, Vector2.Zero, 0.04f, SpriteEffects.None, 0f);

                


                if (gameInfoState.Start_new_Level)
                {
                    String lev = "Level " + BulletLogic.projectiles_enemies_State.LevelCounter;
                    String enter = "\n\n\n\n\n Premi Invio per continuare";
                    Vector2 stringLevHW = font.MeasureString(lev);
                    Vector2 stringEnterHW = font.MeasureString(enter);
                    spriteBatch.DrawString(font, lev,new Vector2(50,50),
                    Color.OrangeRed, 0, stringLevHW/2, 0.2f, SpriteEffects.None, 0f);
                    spriteBatch.DrawString(font, enter, new Vector2(50, 50),
                    Color.OrangeRed, 0, stringEnterHW / 2, 0.04f, SpriteEffects.None, 0f);
                }

                if (gameInfoState.game_over)
                {
                    String lev = "GAME OVER :( ";
                    String enter = "\n\n\n\n\n Premi Invio per tornare al Menu";
                    Vector2 stringLevHW = font.MeasureString(lev);
                    Vector2 stringEnterHW = font.MeasureString(enter);
                    spriteBatch.DrawString(font, lev, new Vector2(50, 50),
                    Color.OrangeRed, 0, stringLevHW / 2, 0.2f, SpriteEffects.None, 0f);
                    spriteBatch.DrawString(font, enter, new Vector2(50, 50),
                    Color.OrangeRed, 0, stringEnterHW / 2, 0.04f, SpriteEffects.None, 0f);
                }
                

                spriteBatch.End();


                

                base.Draw(gameTime);

            } //chiudo if



        }
    }
}
